<template>
    <section class="decoration-edit">
        <section class="l">
            <ul
                    @dragstart="dragStart"
                    @dragend="dragEnd"
            >
                <li
                        v-for="(val, key, index) in typeList"
                        draggable
                        :data-type="key"
                        :key="index + 1"
                >
                    <span :class="val.icon"></span>
                    <p>{{val.name}}</p>
                </li>
            </ul>
        </section>
        <section class="c">
            <!-- header 不可拖拽 -->
            <div class="top-nav" @click="selectType(0)" v-if="info && info.title">
                <img src="./../assets/images/topNavBlack.png">
                <span class="tit">{{ info.title }}</span>
            </div>
            <div
                    class="viewContent"
                    @drop="drog"
                    @dragover="dragOver"
                    :style="{ backgroundColor: info ? info.backgroundColor : '#f5f5f5' }"
            >
                <Draggable
                        v-model="view"
                        draggable=".item"
                >
                    <div ref="viewContent">
                        <template v-for="(item, index) in view">
                            <div
                                    v-if="index > 0"
                                    :data-index="index"
                                    :key="index"
                                    class="item"
                                    :style="{ backgroundColor: item.class.backgroundColor }"
                                    @click="selectType(index)"
                            >
                                <!-- waiting -->
                                <template v-if="item.status && item.status == 2">
                                    <div class="wait"> {{ item.type }} </div>
                                </template>
                                <template v-else>
                                    <component
                                            :is="typeList[item.type]['com']"
                                            :data="item"
                                            :className="className[item.tabType]"
                                    ></component>
                                </template>
                                <i @click="deleteItem($event, index)" class="el-icon-error"></i>
                                <i @mousedown="startScaling($event, index)" class="el-icon-zoom-in scale-icon"></i>
                            </div>
                        </template>
                    </div>
                </Draggable>
            </div>
        </section>
        <section class="r">
            <EditForm
                    :data="props"
                    v-if="isRight"
            ></EditForm>
        </section>
        <div class="submit-btn">
            <el-button @click="submit">提交页面</el-button>
            <!--            <el-button @click="restorePageData">恢复页面</el-button>-->
        </div>
    </section>
</template>

<script>
    import Draggable from 'vuedraggable'
    import EditForm from '@/components/Edit/index'
    import Images from '@/components/View/Images'
    import Banner from '@/components/View/Banner'
    import White from '@/components/View/White'
    import Input from '@/components/View/Input'
    export default {
        components: {
            EditForm,
            Draggable,
            Images,
            Banner,
            White,
            Input
        },
        data() {
            return {
                sub: false,
                typeList: {
                    white: {
                        name: '空白填充',
                        icon: 'el-icon-picture',
                        com: White,
                        backgroundColor: "#f5f5f5"
                    },
                    banner: {
                        name: '轮播图',
                        icon: 'el-icon-picture',
                        com: Banner
                    },
                    images: {
                        name: '图片',
                        icon: 'el-icon-picture',
                        com: Images
                    },
                    input: {
                        name: '输入框',
                        icon: 'el-icon-picture',
                        com: Input
                    },
                },
                view: [
                    {
                        type: 'info',
                        title: '页面标题'
                    }
                ],
                title: '页面标题',
                type: '',
                index: null,        // 当前组件的索引
                isPush: false,      // 是否已添加组件
                props: {},          // 传值
                isRight: false,
                className: {
                    1: 'one',
                    2: 'two',
                    3: 'three'
                },
                savedElements: [],
                isScaling: false,
                startX: 0,
                startY: 0,
                startWidth: 0,
                startHeight: 0,
                currentIndex: null
            }
        },
        computed: {
            info() {
                return this.view[0]
            }
        },
        methods: {
            submit() {
                this.sub = true;
                this.savePageData();
                // JSON 转换会丢失 formData
                const form = JSON.parse(JSON.stringify(this.view))
                if (form.length == 1) {
                    this.$message.error('请添加模块！')
                    return
                }
                this.$message.success('数据提交成功，请按F12打开控制台查看待提交数据集合！')
                console.log(form)  // 提交的数据，根据接口形式修改
                return
            },
            // 保存页面元素以及样式
            savePageData() {
                const elements = this.$refs.viewContent.querySelectorAll("*");
                const result = Array.from(elements).map((el) => {
                    const computedStyle = window.getComputedStyle(el);
                    const rect = el.getBoundingClientRect();
                    return {
                        tag: el.tagName.toLowerCase(), // 元素类型
                        text: el.innerText, // 元素内容
                        styles: {
                            position: computedStyle.position,
                            top: rect.top + "px",
                            left: rect.left + "px",
                            width: rect.width + "px",
                            height: rect.height + "px",
                            backgroundColor: computedStyle.backgroundColor,
                            color: computedStyle.color,
                            fontSize: computedStyle.fontSize,
                            border: computedStyle.border,
                            borderRadius: computedStyle.borderRadius,
                            zIndex: computedStyle.zIndex,
                        },
                        attributes: Array.from(el.attributes).reduce((acc, attr) => {
                            acc[attr.name] = attr.value;
                            return acc;
                        }, {}),
                        // 保存子元素的标签名和索引
                        children: Array.from(el.children).map(child => ({
                            tag: child.tagName.toLowerCase(),
                            index: Array.from(el.children).indexOf(child)
                        })),
                        parent: el.parentNode ? el.parentNode.tagName.toLowerCase() : null // 保存父元素的标签名
                    };
                });
                // 存储数据
                const filter = Array.from(elements).filter(item => item.className === 'item');
                console.log(filter);
                const treeList = [];
                filter.forEach(item => {
                    this.updateElement(item, result);
                    const elementTree = this.buildElementTree(item);
                    treeList.push(elementTree)
                })
                // 输出新的元素树
                console.log(JSON.stringify(treeList));
                localStorage.setItem("savedElements", JSON.stringify(treeList) )
            },
            buildElementTree(element) {
                return {
                    tag: element.tagName?.toLowerCase(), // 元素类型
                    text: element.innerText, // 元素内容
                    styles: {},
                    attributes: Array.from(element.attributes ? element.attributes : []).reduce((acc, attr) => {
                        acc[attr.name] = attr.value;
                        return acc;
                    }, {}),
                    children: Array.from(element.childNodes).filter(item => item.className !== 'el-icon-error'&&  item.className !== 'el-icon-zoom-in scale-icon'
                        && item.nodeName.toString().indexOf("#") < 0).map(child => this.buildElementTree(child)), // 递归获取子元素
                    parent: element.parentNode ? element.parentNode.tagName.toLowerCase() : null // 保存父元素的标签名
                };
            },
            updateElement(node, result) {
                if (!node || !node.childNodes) return;
                // 更新当前节点的 name 属性
                //node.name = node.id.toString();
                // 递归更新子节点的 name 属性
                const className = node.className;
                const filterElement = result.filter(item => item.attributes.class === className)[0];
                if (filterElement) {
                    node.styles = filterElement.styles;
                }
                node.childNodes.forEach(child => this.updateElement(child, result));
            },
            // 切换视图组件
            selectType(index) {
                this.isRight = false
                this.props = this.view[index]
                this.$nextTick(() => this.isRight = true)
            },
            deleteItem(e, index) {
                e.preventDefault()
                e.stopPropagation()
                this.view.splice(index, 1)
                this.isRight = false
                this.props = {}
            },
            // 拖拽类型
            dragStart(e) {
                console.log("dragStart")
                console.log(e.target)
                this.type = e.target.dataset.type
            },
            // 结束拖拽
            dragEnd(e) {
                console.log("dragEnd")
                this.$delete(this.view[this.index], 'status')
                this.isPush = false
                this.type = null
            },
            // 已放置到指定位置
            drog(e) {
                if (!this.type) { // 内容拖拽
                    return
                }
                e.preventDefault()
                e.stopPropagation()
                this.dragEnd()
            },
            // 移动中
            dragOver(e) {
                if (!this.type) { // 内容拖拽
                    return
                }
                e.preventDefault()
                e.stopPropagation()
                let className = e.target.className
                let name = className !== 'viewContent' ? 'item' : 'viewContent'
                const defaultData = {
                    type: this.type,    // 组件类型
                    status: 2,          // 默认状态
                    data: [],           // 数据
                    options: {},         // 选项操作
                    class: {
                        backgroundColor : this.typeList[this.type] ? this.typeList[this.type].backgroundColor : "#fff"
                    }
                }
                if (name == 'viewContent') {
                    if (!this.isPush) {
                        console.log("1")
                        this.index = this.view.length
                        this.isPush = true
                        this.view.push(defaultData)
                    }
                } else if (name == 'item') {
                    let target = e.target
                    let [ y, h, curIndex ] = [ e.offsetY, target.offsetHeight, target.dataset.index ]
                    let direction = y < (h / 2)
                    if (!this.isPush) {
                        // Push to Top or Bottom
                        if (direction) {
                            if (curIndex == 0) {
                                console.log("2")
                                this.view.unshift(defaultData)
                            } else {
                                console.log("3")
                                this.view.splice(curIndex, 0, defaultData)
                            }
                        } else {
                            console.log("4")
                            curIndex = +curIndex + 1
                            this.view.splice(curIndex, 0, defaultData)
                        }
                    } else {
                        // Moving
                        if (direction) {
                            var i = curIndex == 0 ? 0 : curIndex - 1
                            var result = this.view[i]['status'] == 2
                        } else {
                            var i = +curIndex + 1
                            var result = this.view.length > i && this.view[i]['status'] == 2
                        }
                        if (result) return
                        const temp = this.view.splice(this.index, 1)
                        this.view.splice(curIndex, 0, temp[0])
                    }
                    this.index = curIndex
                    this.isPush = true
                }
            },
            startScaling(e, index) {
                e.preventDefault()
                e.stopPropagation()
                this.isScaling = true
                this.currentIndex = index
                this.startX = e.clientX
                this.startY = e.clientY
                this.startWidth = this.$refs.viewContent.childNodes[index].offsetWidth
                this.startHeight = this.$refs.viewContent.childNodes[index].offsetHeight
                document.addEventListener('mousemove', this.scale)
                document.addEventListener('mouseup', this.stopScaling)
            },
            scale(e) {
                if (!this.isScaling) return
                const deltaX = e.clientX - this.startX
                const deltaY = e.clientY - this.startY
                const newWidth = this.startWidth + deltaX
                const newHeight = this.startHeight + deltaY
                const itemElement = this.$refs.viewContent.childNodes[this.currentIndex]
                itemElement.style.width = newWidth + 'px'
                itemElement.style.height = newHeight + 'px'

                // 调整子元素的宽高，忽略包含 class 为 el-icon 开头的子元素
                const childElements = itemElement.querySelectorAll('*:not([class^="el-icon"])')
                childElements.forEach(child => {
                    child.style.width = '100%'
                    child.style.height = '100%'
                })
            },
            stopScaling() {
                this.isScaling = false
                document.removeEventListener('mousemove', this.scale)
                document.removeEventListener('mouseup', this.stopScaling)
            }
        }
    }
</script>



<style lang="scss" scoped>
    .decoration-edit {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 10px 0;
        background: #f7f8f9;
        height: calc(100vh - 50px);
        position: relative;
        .l, .r {
            width: 340px;
            height: 100%;
            padding: 15px 0;
            background: #fff;
        }
        .l {
            ul {
                margin: 0;
                padding: 0;
                li {
                    width: 80px;
                    height: 80px;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    flex-direction: column;
                    cursor: default;
                    list-style: none;
                    font-size: 14px;
                    color: #666;
                    float: left;
                    margin: 0 10px;
                    border-radius: 6px;
                    transition: all .3s;
                    cursor: pointer;
                    &:hover {
                        background: #efefef;
                    }
                    span {
                        display: block;
                        font-size: 40px;
                        margin-bottom: 8px;
                        color: #999;
                    }
                    p {
                        display: block;
                        margin: 0;
                        font-size: 12px;
                    }
                }
            }
        }
        .c {
            width: auto;
            max-width: 400px;
            position: relative;
            .top-nav {
                position: absolute;
                top: 0;
                background: #fff;
                z-index: 999;
                transition: all .3s;
                & * {
                    pointer-events: none;
                }
                &:hover {
                    transform: scale(0.95);
                    border-radius: 10px;
                    overflow: hidden;
                    box-shadow: 0 0 10px #afafaf;
                }
                .tit {
                    position: absolute;
                    left: 50%;
                    bottom: 10px;
                    transform: translateX(-50%);
                }
                img {
                    max-width: 100%;
                    image-rendering: -moz-crisp-edges;
                    image-rendering: -o-crisp-edges;
                    image-rendering: -webkit-optimize-contrast;
                    image-rendering: crisp-edges;
                    -ms-interpolation-mode: nearest-neighbor;
                }
            }
            .viewContent {
                width: 400px;
                height: 700px;
                background: #f5f5f5;
                overflow-y: auto;
                overflow-x: hidden;
                padding-top: 72px;
                box-shadow: 0 2px 6px #ccc;
                &::-webkit-scrollbar {
                    width: 6px;
                }
                &::-webkit-scrollbar-thumb {
                    background: #dbdbdb;
                }
                &::-webkit-scrollbar-track {
                    background: #f6f6f6;
                }
                .item {
                    position: relative;
                    transition: all .3s;
                    background: #fff;
                    &:hover {
                        .el-icon-error, .scale-icon {
                            display: block;
                        }
                    }
                    div {
                        pointer-events: none;
                    }
                    .wait {
                        background: #deedff;
                        height: 35px;
                        text-align: center;
                        line-height: 35px;
                        font-size: 12px;
                        color: #666;
                    }
                    .el-icon-error {
                        position: absolute;
                        right: -10px;
                        top: -6px;
                        color: red;
                        font-size: 25px;
                        cursor: pointer;
                        display: none;
                        z-index: 9999;
                    }
                    .scale-icon {
                        position: absolute;
                        right: -10px;
                        bottom: -6px;
                        color: blue;
                        font-size: 25px;
                        cursor: pointer;
                        display: none;
                        z-index: 9999;
                    }
                }
            }
        }
        .submit-btn {
            position: absolute;
            bottom: 30px;
            left: 50%;
            transform: translateX(-50%);
        }
    }
</style>
